package com.kool.kadmin.system.service;

import com.kool.kadmin.common.bean.PageListResult;
import com.kool.kadmin.common.bean.Result;
import com.kool.kadmin.common.constant.ErrorCode;
import com.kool.kadmin.common.exception.AppException;
import com.kool.kadmin.common.util.PaginatorUtil;
import com.kool.kadmin.common.util.ResultUtil;
import com.kool.kadmin.common.util.StringUtil;
import com.kool.kadmin.system.api.vo.CounterVo;
import com.kool.kadmin.system.bean.SysCounterDo;
import com.kool.kadmin.system.constant.CounterStateEnum;
import com.kool.kadmin.system.dao.SysCounterDao;
import com.kool.kadmin.system.request.AddCntReq;
import com.kool.kadmin.system.request.DeleteCntReq;
import com.kool.kadmin.system.request.GetCntPageReq;
import com.kool.kadmin.system.request.ModifyCntReq;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * 计数器服务
 */
@Service
@Slf4j
public class CounterService {
    @Resource
    private SysCounterDao counterDao;


    /**
     * 取下一个值
     *
     * @param cntCode
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public String nextValue(String cntCode) {
        if (StringUtil.isEmpty(cntCode)) {
            return null;
        }
        //行锁
        SysCounterDo counterDo = counterDao.getAndLock(cntCode);
        if (null == counterDo) {
            return null;
        }

        if (counterDo.getCurValue().equals(counterDo.getMaxValue())) {
            throw new AppException(ErrorCode.BUSINESS_ERROR, "计数器溢出：cntCode = " + cntCode);
        }

        //新值=当前值+1
        String nextValue = StringUtil.add(counterDo.getCurValue(), "1");

        // 如果长度不足，前缀补零
        while (nextValue.length() < counterDo.getMaxValue().length()) {
            nextValue = "0" + nextValue;
        }

        // 更新计数器
        counterDo.setCurValue(nextValue);
        int updNum = counterDao.updateNext(counterDo);

        return nextValue;
    }

    /**
     * 新增计数器
     *
     * @param request
     * @return
     */
    public Result add(AddCntReq request) {
        SysCounterDo counterDo = new SysCounterDo();
        counterDo.setCntCode(request.getCntCode())
                .setCntName(request.getCntName())
                .setCurValue(request.getCurValue())
                .setMinValue(request.getMinValue())
                .setMaxValue(request.getMaxValue())
                .setState(CounterStateEnum.ACTIVE.getCode());
        counterDao.insert(counterDo);
        return ResultUtil.success();
    }

    /**
     * 修改计数器
     *
     * @param request
     * @return
     */
    public Result modify(ModifyCntReq request) {
        SysCounterDo counterDo = new SysCounterDo();
        counterDo.setId(request.getId())
                .setCntCode(request.getCntCode())
                .setCntName(request.getCntName())
                .setCurValue(request.getCurValue())
                .setMinValue(request.getMinValue())
                .setMaxValue(request.getMaxValue())
                .setState(request.getState());
        counterDao.updateById(counterDo);
        return ResultUtil.success();
    }

    /**
     * 删除计数器
     *
     * @param request
     * @return
     */
    public Result delete(DeleteCntReq request) {
        counterDao.deleteById(request.getId());
        return ResultUtil.success();
    }

    /**
     * 分页查询计数器
     *
     * @param request
     * @return
     */
    public PageListResult<SysCounterDo> getPage(GetCntPageReq request) {
        int currentPage = request.getCurrentPage();
        int pageSize = request.getPageSize();
        SysCounterDo counterDo = new SysCounterDo();
        counterDo.setCntCode(request.getCntCode())
                .setCntName(request.getCntName());
        int total = counterDao.countTotal(counterDo);
        int offset = PaginatorUtil.calculateOffset(currentPage, pageSize);
        List<SysCounterDo> counterDos = counterDao.getPage(request.getCntCode(), request.getCntName(), offset, pageSize);
        return ResultUtil.success(counterDos, currentPage, pageSize, total);
    }

    /**
     * @param counterVo
     * @return
     */
    public boolean initCounter(CounterVo counterVo) {
        //查询计数器是否存在
        SysCounterDo sysCounterDo = counterDao.getCounterByCode(counterVo.getCntCode());
        if (sysCounterDo != null) {
            return false;
        } else {
            //插入
            SysCounterDo counterDo = JSON.parseObject(JSON.toJSONString(counterVo), SysCounterDo.class);
            if (StringUtil.isEmpty(counterDo.getCntName())) {
                throw new AppException(ErrorCode.BUSINESS_ERROR, "计数器名称不能为空");
            }
            if (StringUtil.isEmpty(counterDo.getCurValue())) {
                throw new AppException(ErrorCode.BUSINESS_ERROR, "当前值不能为空");
            }
            if (StringUtil.isEmpty(counterDo.getMinValue())) {
                throw new AppException(ErrorCode.BUSINESS_ERROR, "最小值不能为空");
            }
            if (StringUtil.isEmpty(counterDo.getMaxValue())) {
                throw new AppException(ErrorCode.BUSINESS_ERROR, "最大值不能为空");
            }
            counterDo.setState(CounterStateEnum.ACTIVE.getCode());
            counterDao.insert(counterDo);
            return true;
        }
    }
}
